﻿using Furion.Logging;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
using Timo.Api.Core.Filter;
using Timo.Api.Core.Middleware.Lifetime;
using Timo.Logger.Extension;

namespace Timo.Api.Core.Component;

public sealed class StartupServiceComponent : IServiceComponent
{
    public void Load(IServiceCollection services, ComponentContext componentContext)
    {    
        services.AddCorsAccessor().AddControllers().AddNewtonsoftJson(options => {
            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";//时间格式化
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;//忽略循环引用
            //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;//忽略所有 null 属性
            options.SerializerSettings.Converters.AddLongTypeConverters();//long 类型序列化时转 string
            options.SerializerSettings.Converters.AddDateOnlyConverters();   // DateOnly
            options.SerializerSettings.Converters.AddTimeOnlyConverters();   // TimeOnly
            options.SerializerSettings.Converters.AddClayConverters();// 粘土对象 Clay 类型序列化支持
        });
        services.AddInject();        
        //远程请求
        services.AddRemoteRequest();
        // 脱敏检测
        services.AddSensitiveDetection();
        // 任务队列
        services.AddTaskQueue();
        // 控制台格式化
        services.AddConsoleFormatter(options =>
        {
            options.WithTraceId = true;
            options.WithStackFrame = true;
        });        
        //多语言
        services.AddAppLocalization();
        // 配置Nginx转发获取客户端真实IP
        // 注1：如果负载均衡不是在本机通过 Loopback 地址转发请求的，一定要加上options.KnownNetworks.Clear()和options.KnownProxies.Clear()
        // 注2：如果设置环境变量 ASPNETCORE_FORWARDEDHEADERS_ENABLED 为 True，则不需要下面的配置代码
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.All;
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });

        //监听生命周期
        //services.AddSingleton<IHostLifetime, AppLifetime>();
        services.AddHostedService<LifetimeEventsHostedService>();

        #region 监听器
        //不同类型筛选器执行顺序：IAuthorizationFilter -> IResourceFilter -> IActionFilter -> IExceptionFilter -> IResultFilter -> IAlwaysRunResultFilter
        //通常筛选器支持多个，正常情况下，只要调用 await next() 方法都会进去下一个筛选器，但如果通过 context.Result = new XXXResult() 之后，就可以使其短路，也就是不会再执行下一个筛选器。
        //但也有例外：
        //在 IResultFilter/ IAsyncResultFilter 结果筛选器中，则使用标记 context.Cancel = true; 设置短路。
        //在 IExceptionFilter/ IAsyncExceptionFilter 异常筛选器中，则使用标记 context.ExceptionHandled = true; 设置短路
        ////注册全局异常筛选器
        //services.AddMvcFilter<ExceptionFilter>();
        ////注册全局动作筛选器
        //services.AddMvcFilter<ActionFilter>();
        ////注册全局授权筛选器
        //services.AddMvcFilter<AuthorizationFilter>();
        ////注册全局资源请求筛选器
        //services.AddMvcFilter<ResourceFilter>();
        ////注册全局请求结果筛选器筛选器
        //services.AddMvcFilter<ResultFilter>();
        #endregion
    }
}

public sealed class StartupApplicationComponent : IApplicationComponent
{
    public void Load(IApplicationBuilder app, IWebHostEnvironment env, ComponentContext componentContext)
    {
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();       
        // 配置多语言
        app.UseAppLocalization();
        //// 启用HTTPS
        //app.UseHttpsRedirection();
        app.UseCorsAccessor();

        app.UseInject();
        //app.UseEndpoints(endpoints =>
        //{
        //    endpoints.MapControllers();
        //});
        app.MapRouteControllers();

        
    }
}
